﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using DataCenter.Interface;
using DataCenter.Interface.Model;
using DataCenter.Share;
using Microsoft.Data.ConnectionUI;

namespace DataCenter.Utility
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        private SqlConnection _Connection;
        private SqlCommand _Command;
    
        private Dictionary<int, ObjectEntity> DictObject;
        private Dictionary<int, ComponentEntity> DictComponent;
        private Dictionary<int, string> DictType;        

        private void MainForm_Load(object sender, EventArgs e)
        {
            AppDomain.CurrentDomain.UnhandledException += 
                new UnhandledExceptionEventHandler(UnhandledException);
        }
        private void MainForm_Shown(object sender, EventArgs e)
        {
            if (!Initialize())
            {
                this.Close();
                return;
            }
        }
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_Command != null)
            {
                _Command.Dispose();
            }
            if (_Connection != null)
            {
                _Connection.Close();
                _Connection.Dispose();
            }
        }
        private void ShowXmlDialog(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                DataGridView dataGridView = (DataGridView)sender;
                if (e.ColumnIndex == dataGridView.ColumnCount - 1)
                {
                    DataGridViewRow row = dataGridView.Rows[e.RowIndex];
                    ComponentEntity entity = row.Tag as ComponentEntity;
                    if (entity != null)
                    {
                        XmlEditForm xmlForm = new XmlEditForm(entity);
                        if (xmlForm.ShowDialog() == DialogResult.OK)
                        {
                            if (entity.UpdateXmlConfig(_Command))
                            {
                                row.Cells[e.ColumnIndex].Value = entity.ComponentConfig;
                            }
                        }
                    }
                }
            }
        }

        private void toolStripBtnCreateType_Click(object sender, EventArgs e)
        {
            TypeEditForm editForm = new TypeEditForm(_Command);
            if (editForm.ShowDialog() == DialogResult.OK)
            {
                int typeId = editForm.TypeId;
                string typeName = editForm.TypeName;

                int rowIndex = dgvObjectType.Rows.Add();
                dgvObjectType[0, rowIndex].Value = typeId;
                dgvObjectType[1, rowIndex].Value = typeName;

                if (!DictType.ContainsKey(typeId))
                    DictType.Add(typeId, typeName);
            }
        }
        private void toolStripBtnModifyType_Click(object sender, EventArgs e)
        {
            if (dgvObjectType.SelectedRows.Count > 0)
            {
                DataGridViewRow row  = dgvObjectType.SelectedRows[0];
                int typeId = Convert.ToInt32(row.Cells[0].Value);
                string typeName = Convert.ToString(row.Cells[1].Value);

                TypeEditForm editForm = new TypeEditForm(_Command, typeId, typeName);
                if (editForm.ShowDialog() == DialogResult.OK)
                {
                    typeName = editForm.TypeName;

                    row.Cells[1].Value = typeName;
                    if (DictType.ContainsKey(typeId))
                        DictType[typeId] = typeName;
                }
            }
        }
        private void toolStripBtnDropType_Click(object sender, EventArgs e)
        {
            if (dgvObjectType.SelectedRows.Count > 0)
            {
                if (MessageBox.Show("是否要删除数据类型？", this.Text, 
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                    return;
            }

            foreach (DataGridViewRow row in dgvObjectType.SelectedRows)
            {
                int typeId = Convert.ToInt32(row.Cells[0].Value);
                TypeEditForm.Drop(_Command, typeId);
                dgvObjectType.Rows.RemoveAt(row.Index);
                DictType.Remove(typeId);
            }
        }

        private void toolStripBtnCreateObject_Click(object sender, EventArgs e)
        {
            ObjectEditForm editForm = new ObjectEditForm(_Command);
            editForm.InitForm(DictType, DictComponent);
            if (editForm.ShowDialog() == DialogResult.OK)
            {
                ObjectEntity objectEntity = editForm.Entity;
                if (objectEntity != null)
                {
                    ShowObject(objectEntity, -1);

                    if (!DictObject.ContainsKey(objectEntity.ObjectId))
                        DictObject.Add(objectEntity.ObjectId, objectEntity);
                }
            }
        }
        private void toolStripBtnModifyObject_Click(object sender, EventArgs e)
        {
            if (dgvObject.SelectedRows.Count > 0)
            {
                DataGridViewRow row = dgvObject.SelectedRows[0];
                ObjectEntity objectEntity = row.Tag as ObjectEntity;
                if (objectEntity != null)
                {
                    ObjectEditForm editForm = new ObjectEditForm(_Command, objectEntity);
                    editForm.InitForm(DictType, DictComponent);
                    if(editForm.ShowDialog() == DialogResult.OK)
                    {
                        ShowObject(objectEntity, row.Index);
                    }
                }
            }
        }
        private void toolStripBtnDropObject_Click(object sender, EventArgs e)
        {
            if (dgvObject.SelectedRows.Count > 0)
            {
                if (MessageBox.Show("是否要删除对象？", this.Text,
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                    return;

                foreach (DataGridViewRow row in dgvObject.SelectedRows)
                {
                    ObjectEntity entity = row.Tag as ObjectEntity;
                    if (entity != null)
                    {
                        if (entity.Drop(_Command))
                        {
                            dgvObject.Rows.Remove(row);
                            DictObject.Remove(entity.ObjectId);
                        }
                    }
                }
            }
        }

        private void toolStripBtnCreateSource_Click(object sender, EventArgs e)
        {
            ComponentEntity entity = CreateComponent(typeof(DataSourceAttribute));
            if (entity != null) ShowComponent(dgvDataSource, entity);
        }
        private void toolStripBtnModifySource_Click(object sender, EventArgs e)
        {
            UpdateComponent(dgvDataSource);
        }
        private void toolStripBtnDropSource_Click(object sender, EventArgs e)
        {
            DropComponent(dgvDataSource);
        }

        private void toolStripBtnCreateAdapter_Click(object sender, EventArgs e)
        {
            ComponentEntity entity = CreateComponent(typeof(AdapterAttribute));
            if (entity != null) ShowComponent(dgvAdapter, entity);
        }
        private void toolStripBtnModifyAdapter_Click(object sender, EventArgs e)
        {
            UpdateComponent(dgvAdapter);
        }
        private void toolStripBtnDropAdapter_Click(object sender, EventArgs e)
        {
            DropComponent(dgvAdapter);
        }

        private void toolStripBtnCreateProcessor_Click(object sender, EventArgs e)
        {
            ComponentEntity entity = CreateComponent(typeof(ProcessorAttribute));
            if (entity != null) ShowComponent(dgvProcessor, entity);
        }
        private void toolStripBtnModifyProcessor_Click(object sender, EventArgs e)
        {
            UpdateComponent(dgvProcessor);
        }
        private void toolStripBtnDropProcessor_Click(object sender, EventArgs e)
        {
            DropComponent(dgvProcessor);
        }

        private void toolStripBtnCreateCalculator_Click(object sender, EventArgs e)
        {
            ComponentEntity entity = CreateComponent(typeof(CalculatorAttribute));
            if (entity != null) ShowComponent(dgvCalculator, entity);
        }
        private void toolStripBtnModifyCalculator_Click(object sender, EventArgs e)
        {
            UpdateComponent(dgvCalculator);
        }
        private void toolStripBtnDropCalculator_Click(object sender, EventArgs e)
        {
            DropComponent(dgvCalculator);
        }

        private void btnBrowser_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                txtAppPath.Text = openFileDialog1.FileName;
            }
        }
        private void btnSave_Click(object sender, EventArgs e)
        {
            if (Check())
            {
                CenterSetting centerSetting = CenterSetting.GetInstance();
                centerSetting.MaxMemoryLimit = Convert.ToInt32(txtMemoryLimit.Text);
                centerSetting.AppFilePath = txtAppPath.Text;
                centerSetting.Update(_Command);

                TableSetting tableSetting = TableSetting.GetInstance();
                tableSetting.SplitMonthStep = Convert.ToInt32(cboSplitMonthStep.SelectedItem);
                tableSetting.TableName = txtTableName.Text.Trim();
                tableSetting.Update(_Command);

                MessageBox.Show("数据中心配置保存成功。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private bool Initialize()
        {
            if (!InitConnection()) return false;
            if (!InitComponent()) return false;
            if (!InitObjectType()) return false;
            if (!InitObject()) return false;
            if (!InitOption()) return false;
            return true;
        }
        private bool InitConnection()
        {
            try
            {
                DataConnectionDialog dialog = new DataConnectionDialog();
                dialog.DataSources.Add(DataSource.SqlDataSource);
                dialog.SelectedDataProvider = DataProvider.SqlDataProvider;
                if (DataConnectionDialog.Show(dialog, this) == DialogResult.OK)
                {
                    _Connection = new SqlConnection(dialog.ConnectionString);
                    _Connection.Open();

                    _Command = _Connection.CreateCommand();
                    _Command.CommandTimeout = 0;

                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                MessageBox.Show("初始化数据库连接失败\r\n" + ex.Message, this.Text,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
        private bool InitObject()
        {
            try
            {
                DictObject = ObjectEntity.Search(_Command, "");
                foreach (ObjectEntity objectEntity in DictObject.Values)
                {
                    ShowObject(objectEntity, -1);
                }
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("初始化对象失败\r\n" + ex.Message, this.Text,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
        private bool InitComponent()
        {
            try
            {
                DictComponent = ComponentEntity.Search(_Command, "");
                foreach (ComponentEntity entity in DictComponent.Values)
                {
                    DataGridView dataGridView = null;
                    switch (entity.ComponentType)
                    {
                        case ComponentTypes.Source: dataGridView = dgvDataSource; break;
                        case ComponentTypes.Adapter: dataGridView = dgvAdapter; break;
                        case ComponentTypes.Processor: dataGridView = dgvProcessor; break;
                        case ComponentTypes.Calculator: dataGridView = dgvCalculator; break;
                    }
                    ShowComponent(dataGridView, entity);
                }

                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("初始化组件失败\r\n" + ex.Message, this.Text,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
        private bool InitObjectType()
        {
            try
            {
                DictType = new Dictionary<int, string>();

                string commandString = "SELECT * FROM ObjectType ORDER BY TypeId";
                _Command.CommandText = commandString;
                _Command.CommandType = CommandType.Text;

                using (SqlDataReader reader = _Command.ExecuteReader())
                {
                    while (reader.Read())
                    {                        
                        int typeId = Utils.GetReaderValue<int>(reader, "TypeId");
                        string typeName = Utils.GetReaderValue<string>(reader, "TypeName");

                        int rowIndex = dgvObjectType.Rows.Add();
                        dgvObjectType[0, rowIndex].Value = typeId;
                        dgvObjectType[1, rowIndex].Value = typeName;

                        if (!DictType.ContainsKey(typeId))
                            DictType.Add(typeId, typeName);
                    }                    
                }
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("初始化对象类型失败\r\n" + ex.Message, this.Text,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
        private bool InitOption()
        {
            CenterSetting.GetInstance().Initialize(_Command);
            TableSetting.GetInstance().Initialize(_Command);

            ShowOption();

            return true;
        }

        private ComponentEntity CreateComponent(Type factoryType)
        {
            OpenAssemblyForm openForm = new OpenAssemblyForm(factoryType);
            if (openForm.ShowDialog() == DialogResult.OK)
            {
                ComponentEntity entity = openForm.Entity;
                if (entity.Create(_Command))
                    return entity;
            }
            return null;
        }        

        private void ShowComponent(DataGridView dataGridView, ComponentEntity entity)
        {
            int rowIndex = dataGridView.Rows.Add();
            dataGridView[0, rowIndex].Value = entity.ComponentId;
            dataGridView[1, rowIndex].Value = entity.ComponentName;
            dataGridView[2, rowIndex].Value = entity.AssemblyName;
            dataGridView[3, rowIndex].Value = entity.TypeName;
            dataGridView[4, rowIndex].Value = entity.ComponentConfig;
            dataGridView.Rows[rowIndex].Tag = entity;

            if (!DictComponent.ContainsKey(entity.ComponentId))
            {
                DictComponent.Add(entity.ComponentId, entity);
            }
        }
        private void UpdateComponent(DataGridView dataGridView)
        {
            if (dataGridView.SelectedRows.Count > 0)
            {
                DataGridViewRow row = dataGridView.SelectedRows[0];
                ComponentEntity entity = row.Tag as ComponentEntity;
                if (entity != null)
                {
                    if (entity.Modify(_Command))
                    {
                        row.Cells[0].Value = entity.ComponentId;
                        row.Cells[1].Value = entity.ComponentName;
                        row.Cells[2].Value = entity.AssemblyName;
                        row.Cells[3].Value = entity.TypeName;
                        row.Cells[4].Value = entity.ComponentConfig;
                    }
                }
            }
        }
        private void DropComponent(DataGridView dataGridView)
        {
            if (dataGridView.SelectedRows.Count > 0)
            {
                if (MessageBox.Show("是否要删除数据源？", this.Text,
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                    return;

                foreach (DataGridViewRow row in dataGridView.SelectedRows)
                {
                    ComponentEntity entity = row.Tag as ComponentEntity;
                    if (entity != null)
                    {
                        if (entity.Drop(_Command))
                        {
                            dataGridView.Rows.Remove(row);
                            DictComponent.Remove(entity.ComponentId);
                        }
                    }
                }
            }
        }

        private void ShowObject(ObjectEntity objectEntity, int rowIndex)
        {
            if (rowIndex == -1) rowIndex = dgvObject.Rows.Add();

            dgvObject["colObjectId", rowIndex].Value = objectEntity.ObjectId;
            dgvObject["colObjectName", rowIndex].Value = objectEntity.ObjectName;
            dgvObject["colObjectKey", rowIndex].Value = objectEntity.ObjectKey;

            string typeName = "(" + objectEntity.ObjectType.ToString() + ")";
            if (DictType.ContainsKey(objectEntity.ObjectType))
                typeName = DictType[objectEntity.ObjectType] + typeName;
            dgvObject["colObjectType", rowIndex].Value = typeName;

            if (objectEntity.CanImport)
            {
                dgvObject["colBindingSourceName", rowIndex].Value = GetComponentName(objectEntity.BindingSourceId);
                dgvObject["colBindingAdapterName", rowIndex].Value = GetComponentName(objectEntity.BindingAdapterId);
            }
            else
            {
                dgvObject["colBindingSourceName", rowIndex].Value = "";
                dgvObject["colBindingAdapterName", rowIndex].Value = "";
            }
            if (objectEntity.CanProcess)
            {
                dgvObject["colBindingProcessorName", rowIndex].Value = GetComponentName(objectEntity.BindingProcessorId);
            }
            else
            {
                dgvObject["colBindingProcessorName", rowIndex].Value = null;
            }
            if (objectEntity.CanCalculate)
            {
                dgvObject["colBindingCalculatorName", rowIndex].Value = GetComponentName(objectEntity.BindingCalculatorId);
            }
            else
            {
                dgvObject["colBindingCalculatorName", rowIndex].Value = "";
            }
            dgvObject["colObjectDefaultValue", rowIndex].Value = objectEntity.DefaultValue;
            dgvObject["colObjectUnit", rowIndex].Value = objectEntity.Unit;
            dgvObject.Rows[rowIndex].Tag = objectEntity;
        }
        private string GetComponentName(int componentId)
        {
            string componentName = componentId.ToString();
            if (DictComponent.ContainsKey(componentId))
                componentName = DictComponent[componentId].ComponentName + " (" + componentName + ")";
            return componentName;
        }
        private void UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception ex = (Exception)e.ExceptionObject;
            MessageBox.Show("发生严重错误\r\n" + ex.Message + "\r\n" + ex.StackTrace);
            this.Close();
        }

        private bool Check()
        {
            bool checkResult = true;
            string errmsg = "";
            Control ctrl = null;

            int iValue;
            double dValue;
            if (string.IsNullOrEmpty(txtMemoryLimit.Text))
            {
                errmsg = "最大内存限制不能为空";
                ctrl = txtMemoryLimit;
                goto ShowError;
            }
            if (!double.TryParse(txtMemoryLimit.Text, out dValue))
            {
                errmsg = "最大内存限制必须有效的浮点数";
                ctrl = txtMemoryLimit;
                goto ShowError;
            }
            if (dValue < 0 || dValue > int.MaxValue)
            {
                errmsg = "最大内存限制必须在 0 ~ 2GB 之内";
                ctrl = txtMemoryLimit;
                goto ShowError;
            }

            if (string.IsNullOrEmpty(txtAppPath.Text))
            {
                errmsg = "App文件路径不能为空";
                ctrl = txtMemoryLimit;
                goto ShowError;
            }
            if (!File.Exists(txtAppPath.Text))
            {
                errmsg = string.Format("App文件\"{0}\"不存在", txtAppPath.Text);
                ctrl = txtMemoryLimit;
                goto ShowError;
            }

            if (string.IsNullOrEmpty(txtTableName.Text))
            {
                errmsg = "数据表名称不能为空";
                ctrl = txtTableName;
                goto ShowError;
            }

        ShowError:
            if (!string.IsNullOrEmpty(errmsg))
            {
                MessageBox.Show(errmsg, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                if (ctrl != null) ctrl.Focus();
                checkResult = false;
            }

            return checkResult;
        }
        private void ShowOption()
        {
            CenterSetting centerSetting = CenterSetting.GetInstance();
            txtMemoryLimit.Text = centerSetting.MaxMemoryLimit.ToString();
            txtAppPath.Text = centerSetting.AppFilePath;

            TableSetting tableSetting = TableSetting.GetInstance();
            txtTableName.Text = tableSetting.TableName;
            cboSplitMonthStep.SelectedIndex = tableSetting.SplitMonthStep - 1;
            txtStartIndex.Text = tableSetting.StartTableIndex.ToString();
            txtEndIndex.Text = tableSetting.EndTableIndex.ToString();
        }
    }
}
